#include <STC8G.H>

#include "type.h"
#include "uart.h"

//当前系统时钟为: 11.0592Mhz
//串口波特率为 9600

#define BUFFER_SIZE 32
static xdata uint8_t rx_buffer[32];
xdata volatile unsigned char rx_index = 0;
volatile bit data_ready = 0;
static xdata uint8_t time0_count;

void Timer0_Isr(void) interrupt 1
{
    TF0 = 0;
    // P33 = ~P33; // 切换P3.3引脚状态，用于指示定时器中断
	  time0_count++;
    if(time0_count >= 30) {
		rx_index = 0;
		data_ready = 0;
        TR0 = 0; // 停止定时器0
        time0_count = 0; // 重置计数器
    }
}

void Timer0_Init(void)		//1毫秒@11.0592MHz
{
	AUXR |= 0x80;			//定时器时钟1T模式
	TMOD &= 0xF0;			//设置定时器模式
	TL0 = 0xCD;				//设置定时初始值
	TH0 = 0xD4;				//设置定时初始值
	TF0 = 0;				//清除TF0标志
	TR0 = 0;				//定时器0 停止计时
	ET0 = 1;				//使能定时器0中断
}



// 串口初始化
void UART_Init(uint8_t band) {
    time0_count = 0; // 初始化定时器计数
	Timer0_Init();

    SCON = 0x50;        // 8位数据,可变波特率
    AUXR |= 0x40;       // 定时器1时钟为Fosc,即1T
    AUXR &= 0xFE;       // 串口1选择定时器1为波特率发生器
    TMOD &= 0x0F;       // 设定定时器1为16位自动重装方式

    if(band == Band_4800){
        TL1 = 0xC0;			//设置定时初始值
        TH1 = 0xFD;			//设置定时初始值
	} else if (band == Band_9600) {
        TL1 = 0xE0;         // 设定定时初值
        TH1 = 0xFE;         // 设定定时初值
	} else if (band == Band_14400) {
        TL1 = 0x40;			//设置定时初始值
        TH1 = 0xFF;			//设置定时初始值
	} else if (band == Band_19200) {
        TL1 = 0x70;			//设置定时初始值
        TH1 = 0xFF;			//设置定时初始值
	} else if (band == Band_28800) {
        TL1 = 0xA0;			//设置定时初始值
        TH1 = 0xFF;			//设置定时初始值
	} else if (band == Band_38400) {
        TL1 = 0xB8;			//设置定时初始值
        TH1 = 0xFF;			//设置定时初始值
	} else if (band == Band_57600) {
        TL1 = 0xD0;			//设置定时初始值
        TH1 = 0xFF;			//设置定时初始值
	} else if(band == Band_115200){
		TL1 = 0xE8;			//设置定时初始值
		TH1 = 0xFF;			//设置定时初始值		
	}else{
        TL1 = 0xE0;         // 设定定时初值
        TH1 = 0xFE;         // 设定定时初值
    }
    ET1 = 0;			//禁止定时器中断
    TR1 = 1;			//定时器1开始计时
    ES = 1;             // 使能串口中断
    EA = 1;             // 开启全局中断
}

// 发送字符串
void UART_SendString(char *s) {
    //判断是否正在接收数据
    while(rx_index!=0);
	P32 = 1; // 发送使能引脚,用于控制485芯片开始发送数据
    while(*s) {
        SBUF = *s++;
        while(!TI);
        TI = 0;
    }
	P32 = 0; // 发送完成后禁用发送使能引脚,此时485芯片将接收数据写入RXD引脚
}

void Uart_ISR(void) interrupt 4 {
    if(RI) {
        RI = 0;        // 必须手动清除接收标志
        if(rx_index == 0){
            time0_count = 0; // 重置计数器
            TR0 = 1; // 启动定时器0
        }
        rx_buffer[rx_index] = SBUF; // 读取接收数据
        // 检测结束符（如回车换行）
        if(rx_buffer[rx_index] == '\n' && rx_buffer[rx_index - 1] == '\r') {
            rx_buffer[rx_index - 1] = '\0'; // 终止字符串
            data_ready = 1;      // 设置数据就绪标志
            rx_index = 0;        // 重置索引
            TR0 = 0; // 停止定时器0
        } else {
            if(++rx_index >= BUFFER_SIZE) {
                rx_index = 0;  // 防溢出
                data_ready = 0; // 重置数据就绪标志
                rx_buffer[rx_index] = '\0'; // 确保字符串终止
                TR0 = 0; // 停止定时器0
            }
        }
    }
}

// static int my_atoi(const char *str) {
//     int result = 0;
//     int sign = 1;
//     while (*str == ' ' || *str == '\t') { // 跳过空格和制表符
//         str++;
//     }
//     // 处理符号
//     if (*str == '-') {
//         sign = -1;
//         str++;
//     } else if (*str == '+') {
//         str++;
//     }

//     // 转换数字字符到整数
//     while (*str >= '0' && *str <= '9') {
//         result = result * 10 + (*str - '0');
//         str++;
//     }

//     return result * sign;
// }
static uint32_t my_atol(const char *str)
{
    uint32_t result = 0;
    int sign = 1; // 默认为正数
    while (*str == ' ' || *str == '\t') { // 跳过空格和制表符
        str++;
    }
    // 处理符号
    if (*str == '-') {
        sign = -1;
        str++;
    } else if (*str == '+') {
        str++;
    } 

    while (*str >= '0' && *str <= '9') {
        result = result * 10 + (*str - '0');
        str++;
    }
    return result * sign;
}

// 简单实现 strcmp
int my_strcmp(const char *s1, const char *s2) {
    while (*s1 && *s2 && *s1 == *s2) {
        s1++;
        s2++;
    }
    return (unsigned char)*s1 - (unsigned char)*s2;
}

// 简单实现 strncmp
int my_strncmp(const char *s1, const char *s2, unsigned int n) {
    while (n > 0 && *s1 && *s2 && *s1 == *s2) {
        s1++;
        s2++;
        n--;
    }
    if (n == 0) {
        return 0;
    }
    return (unsigned char)*s1 - (unsigned char)*s2;
}

uint8_t Uart_status(uint8_t *_data) {
    if(data_ready) {
        data_ready = 0;
        //判断 rx_buffer 的内容是否为 "Query"
        if(my_strncmp(rx_buffer, "Query ", 6) == 0) {
            uint8_t address = (uint8_t)my_atol((char *)(rx_buffer + 6));
            *_data = address; // 返回地址值
            return 1;// 返回查询请求成功
        }
        //判断 rx_buffer 的内容是否为 "Address xx", 后面的 xx 为 0-255 之间的数字
        else if(my_strncmp(rx_buffer, "Address ", 8) == 0) {
            uint8_t address = (uint8_t)my_atol((char *)(rx_buffer + 8));
            if(address < 256) {
                *_data = address; // 返回地址值
                return 2; // 返回地址设置
            }
        }
        // 判断 rx_buffer 的内容是否为 "Address"
        else if(my_strcmp(rx_buffer, "Address") == 0) {
            return 3; // 返回地址查询请求
        }
        // 判断 rx_buffer 的内容是否为 "Band"
        else if(my_strcmp(rx_buffer, "Band") == 0) {
            return 4; // 返回地址查询请求
        }
        //判断 rx_buffer 的内容是否为 "Band xxxx", 后面的 xx 为 4800 - 115200 之间的数字
        else if(my_strncmp(rx_buffer, "Band ", 5) == 0) {
            uint32_t band = (uint32_t)my_atol((char *)(rx_buffer + 5));
            if(band == 4800) *_data = (uint8_t)Band_4800;
            else if(band == 9600) *_data = (uint8_t)Band_9600;
            else if(band == 14400) *_data = (uint8_t)Band_14400;
            else if(band == 19200) *_data = (uint8_t)Band_19200;
            else if(band == 28800) *_data = (uint8_t)Band_28800;
            else if(band == 38400) *_data = (uint8_t)Band_38400;
            else if(band == 57600) *_data = (uint8_t)Band_57600;
            else if(band == 115200) *_data = (uint8_t)Band_115200;
            else *_data = (uint8_t)Band_9600; // 返回无效波特率
            return 5; // 返回波特率设置
        }
    }
    return 0; // 返回无数据
}



